<?php
//+-----------------------------------------------------------
//| 人生是荒芜的旅行，冷暖自知，苦乐在心
//+-----------------------------------------------------------
//| Author:Janmas <janmas@126.com>
//+-----------------------------------------------------------
//| 
//+-----------------------------------------------------------


namespace app\admin\service;


use app\admin\exception\DataNotFoundException;
use app\admin\exception\LogicException;
use app\admin\model\Permession;
use think\facade\Event;
use think\Request;

class Auth
{

    public static $instance;

    protected $logined = false;

    /**
     * 当前菜单id
     * @var int
     */
    public $currentMenuId = 0;

    /**
     * 权限节点列表
     * @var array
     */
    public $ruleList = [];

    public static function instance()
    {
        if (!self::$instance instanceof self) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 登录
     * @param string $account
     * @param string $passwd
     * @return bool
     */
    public function login($account = '', $passwd = '')
    {

        $user = \app\admin\model\User::where('account', $account)->findOrEmpty();

        if ($user->isEmpty()) {
            throw new DataNotFoundException('用户不存在');
        }

        if ($user->status < 1) {
            throw new LogicException('用户被禁用');
        }

        if (!password_verify($passwd, $user->passwd)) {
            throw new LogicException('密码错误');
        }
        $user->hidden(['passwd', 'account', 'id']);
        session('userModel', $user);
        session('SYSTEM_ID', $user->id);
        session('system_user', $user->toArray());
        session('syste_role_id', $user->role);
        Event::trigger('UserLogin');
        $this->logined = true;
        return true;
    }

    /**
     * 检查是否登录
     * @return bool
     */
    public function isLogin()
    {
        if ($this->logined) {
            return true;
        }
        if (session('?system_user')) {
            $this->logined = true;
            return true;
        } else {
            $this->logined = false;
            return false;
        }
    }

    /**
     * 权限检测
     * @return bool
     */
    public function auth($requestUri)
    {
        $this->getRuleMap(session('SYSTEM_ID'));
        if(session('SYSTEM_ID') == 1){
            return true;
        }

        $node = $this->parseNode($requestUri);
        /**
         * @var String $controller
         * @var String $action
         */
        extract($node);
        $link = app('http')->getName() . '/' . join('/', $node);
        $rule = [
            'link' => $link,
            'controller' => $controller,
            'action' => $action
        ];
        $this->currentMenuId = array_search($rule, $this->ruleList);
        if ($this->currentMenuId !== false) {
            return true;
        } else {
            $this->currentMenuId = 0;
            return false;
        }
    }

    /**
     * 过滤不需要登录
     * @param Request $request
     * @param array $noNeedLogin
     * @return bool
     */
    public function noNeedLogin(Request $request, $noNeedLogin = [])
    {
        $noNeedLogin = array_map('strtolower', $noNeedLogin);
        if (in_array('*', $noNeedLogin)) {
            return true;
        } elseif (in_array($this->getCurrentActionName($request), $noNeedLogin)) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 过滤不需要检测权限的方法
     * @param Request $request
     * @param $noNeedAuth
     * @return bool
     */
    public function noNeedAuth(Request $request, $noNeedAuth)
    {
        $noNeedAuth = array_map('strtolower', $noNeedAuth);
        if (in_array('*', $noNeedAuth)) {
            return true;
        }
        if (in_array($this->getCurrentActionName($request), $noNeedAuth)) {
            return true;
        }
        return false;
    }

    /**
     * 获取权限列表
     * @param int $adminId
     * @param false $getTree
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getRuleMap($adminId = 0, $getTree = false)
    {
        if ($this->ruleList && !$getTree ) {
            return $this->ruleList;
        }

        $systemUserInfo = \app\admin\model\User::find($adminId);
        if (!$systemUserInfo) {
            throw new LogicException('管理员不存在');
        }

        $roleSubSql = \app\admin\model\UserRole::where('admin_id',$adminId)->field('role_id')->buildSql();
        $permessionSubSql = Permession::where('role_id IN ' . $roleSubSql)->field('permession_id')->buildSql();

        if ($getTree) {
            $menu = \app\admin\model\Menu::show()->where('id IN ' . $permessionSubSql)->where('type', 'in', [0, 1])->where('flag', app('http')->getName())->field('id,pid,name,icon,sort,link')->order('sort asc')->select();
            if (!$menu) {
                return [];
            }
            return recursion($menu->toArray());
        } else {
            $menu = \app\admin\model\Menu::where('id IN' . $permessionSubSql)->field('link,controller,action,id,type,flag')->select();
            if (!$menu) {
                return [];
            }
            $newMenu = [];
            foreach ($menu as $value) {
                $action = empty($value->action)?'index':$value->action;
                $link = empty($value->link)?$value->controller . '/' . $action:$value->link;
                $newMenu[$value->id] = [
                    'link' => $value->flag . '/' . $link,
                    'controller' => $value->controller,
                    'action' => $action,
                ];
            }
            $newMenu[0] = [
                'link' => 'admin/Index/index',
                'controller' => 'Index',
                'action' => 'index'
            ];
            $this->ruleList = $newMenu;
            return;
        }
    }

    /**
     * 获取当前方法名
     * @param Request $request
     * @return string
     */
    protected function getCurrentActionName(Request $request)
    {
        return strtolower($request->action());

    }

    /**
     * 解析当前节点为可用格式
     * @param string $requestUri
     * @return array
     */
    protected function parseNode(string $requestUri)
    {

        $requestUri = substr($requestUri, 0, -5);
        $requestUriTmp = explode('/', $requestUri);
        $action = array_pop($requestUriTmp);
        $action = empty($action) ? 'index' : $action;
        $controller = ucfirst(array_pop($requestUriTmp));
        return ['controller' => $controller, 'action' => $action];
    }
}